<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Expires" content="0">
    <title>AI Worker - 智能测试平台</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
            background: linear-gradient(135deg, #0e7490 0%, #0891b2 50%, #06b6d4 100%);
            min-height: 100vh;
            padding: 20px;
        }

        .container {
            max-width: 1400px;
            margin: 0 auto;
            background: white;
            border-radius: 12px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            overflow: hidden;
        }

        .header {
            background: linear-gradient(135deg, #0e7490 0%, #0891b2 100%);
            color: white;
            padding: 40px 30px;
            text-align: center;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
        }

        .header h1 {
            font-size: 32px;
            margin-bottom: 10px;
        }

        .header p {
            font-size: 16px;
            opacity: 0.9;
        }

        .content {
            padding: 30px;
        }

        .main-tabs {
            display: flex;
            gap: 10px;
            margin-bottom: 30px;
            border-bottom: 2px solid #e0e0e0;
        }

        .main-tab {
            padding: 15px 30px;
            background: none;
            border: none;
            cursor: pointer;
            font-size: 18px;
            color: #666;
            transition: all 0.3s;
            border-bottom: 3px solid transparent;
            font-weight: 500;
        }

        .main-tab.active {
            color: #0891b2;
            border-bottom-color: #0891b2;
            font-weight: bold;
        }

        .main-tab:hover {
            color: #0891b2;
        }

        .main-tab-content {
            display: none;
        }

        .main-tab-content.active {
            display: block;
            animation: fadeIn 0.3s;
        }

        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }

        /* 项目卡片样式 - 长条展示 */
        .projects-grid {
            display: flex;
            flex-direction: column;
            gap: 15px;
            margin-top: 20px;
        }

        .project-card {
            border: 2px solid #e0e0e0;
            border-radius: 8px;
            padding: 20px;
            transition: all 0.3s;
            display: flex;
            justify-content: space-between;
            align-items: center;
            cursor: pointer;
        }

        .project-card:hover {
            border-color: #0891b2;
            box-shadow: 0 6px 20px rgba(8, 145, 178, 0.15);
            transform: translateY(-2px);
        }

        .project-info {
            flex: 1;
        }

        .project-card h3 {
            color: #333;
            margin-bottom: 8px;
            font-size: 18px;
        }

        .project-card p {
            color: #666;
            font-size: 14px;
            margin: 0;
        }

        .project-meta {
            font-size: 13px;
            color: #999;
            margin-top: 8px;
        }

        .project-actions {
            display: flex;
            gap: 10px;
            flex-shrink: 0;
            align-items: center;
        }

        .btn-icon {
            padding: 8px 12px;
            font-size: 0.9em;
        }

        .btn-delete {
            background: white;
            color: #dc3545;
            border: 2px solid #dc3545;
            position: relative;
            overflow: hidden;
        }

        .btn-delete::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 0;
            height: 0;
            border-radius: 50%;
            background: #dc3545;
            transform: translate(-50%, -50%);
            transition: width 0.3s, height 0.3s;
            z-index: 0;
        }

        .btn-delete:hover {
            color: white;
            border-color: #dc3545;
        }

        .btn-delete:hover::before {
            width: 300px;
            height: 300px;
        }

        .btn-delete span {
            position: relative;
            z-index: 1;
        }

        .btn {
            padding: 10px 20px;
            border: none;
            border-radius: 8px;
            font-size: 14px;
            cursor: pointer;
            transition: all 0.3s;
            font-weight: 600;
        }

        .btn-primary {
            background: linear-gradient(135deg, #0891b2 0%, #06b6d4 100%);
            color: white;
            box-shadow: 0 2px 8px rgba(8, 145, 178, 0.2);
        }

        .btn-primary:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 16px rgba(8, 145, 178, 0.3);
            background: linear-gradient(135deg, #0e7490 0%, #0891b2 100%);
        }

        .btn-secondary {
            background: #6c757d;
            color: white;
        }

        .btn-secondary:hover {
            background: #5a6268;
        }

        .btn-success {
            background: #10b981;
            color: white;
            box-shadow: 0 2px 8px rgba(16, 185, 129, 0.2);
        }

        .btn-success:hover {
            background: #059669;
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
        }

        .btn-danger {
            background: #ef4444;
            color: white;
            box-shadow: 0 2px 8px rgba(239, 68, 68, 0.2);
        }

        .btn-danger:hover {
            background: #dc2626;
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
        }

        .add-project-btn {
            position: fixed;
            bottom: 40px;
            right: 40px;
            width: 60px;
            height: 60px;
            border-radius: 50%;
            background: linear-gradient(135deg, #0891b2 0%, #06b6d4 100%);
            color: white;
            border: none;
            font-size: 30px;
            cursor: pointer;
            box-shadow: 0 6px 24px rgba(8, 145, 178, 0.3);
            transition: all 0.3s;
        }

        .add-project-btn:hover {
            transform: scale(1.1) rotate(90deg);
            box-shadow: 0 8px 32px rgba(8, 145, 178, 0.4);
        }

        .empty-state {
            text-align: center;
            padding: 60px 20px;
            color: #999;
        }

        .empty-state h3 {
            font-size: 24px;
            margin-bottom: 10px;
        }

        /* Case Input 样式 */
        .case-input-container {
            max-width: 100%;
        }

        .form-group {
            margin-bottom: 20px;
        }

        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 600;
            color: #333;
        }

        input[type="text"],
        select,
        textarea {
            width: 100%;
            padding: 12px;
            border: 2px solid #e0e0e0;
            border-radius: 8px;
            font-size: 14px;
            transition: border-color 0.3s;
            font-family: inherit;
        }

        input[type="text"]:focus,
        select:focus,
        textarea:focus {
            outline: none;
            border-color: #0891b2;
            box-shadow: 0 0 0 3px rgba(8, 145, 178, 0.1);
        }
        
        select {
            background: white;
            cursor: pointer;
        }
        
        select option {
            padding: 10px;
        }

        textarea {
            resize: vertical;
            min-height: 120px;
            font-family: 'Courier New', monospace;
        }

        .sub-tabs {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
            border-bottom: 2px solid #f0f0f0;
        }

        .sub-tab {
            padding: 10px 20px;
            background: none;
            border: none;
            cursor: pointer;
            font-size: 15px;
            color: #666;
            transition: all 0.3s;
            border-bottom: 2px solid transparent;
        }

        .sub-tab.active {
            color: #667eea;
            border-bottom-color: #667eea;
            font-weight: 600;
        }

        .sub-tab-content {
            display: none;
        }

        .sub-tab-content.active {
            display: block;
        }

        .case-list {
            display: grid;
            gap: 20px;
        }

        .case-item {
            border: 2px solid #e0e0e0;
            border-radius: 8px;
            padding: 20px;
            transition: all 0.3s;
        }

        .case-item:hover {
            border-color: #667eea;
            box-shadow: 0 5px 15px rgba(102, 126, 234, 0.2);
        }

        .case-header {
            display: flex;
            justify-content: space-between;
            align-items: start;
            margin-bottom: 15px;
        }

        .case-title {
            font-size: 18px;
            font-weight: bold;
            color: #333;
            margin-bottom: 5px;
        }

        .case-id {
            color: #999;
            font-size: 14px;
        }

        .case-actions {
            display: flex;
            gap: 8px;
        }

        .case-actions .btn {
            padding: 8px 16px;
            font-size: 14px;
        }

        .method-badge {
            display: inline-block;
            padding: 4px 12px;
            border-radius: 4px;
            font-size: 12px;
            font-weight: bold;
            color: white;
        }

        .method-GET { background: #2196F3; }
        .method-POST { background: #4CAF50; }
        .method-PUT { background: #FF9800; }
        .method-DELETE { background: #F44336; }
        .method-PATCH { background: #9C27B0; }

        .loading {
            display: inline-block;
            width: 20px;
            height: 20px;
            border: 3px solid rgba(255,255,255,.3);
            border-radius: 50%;
            border-top-color: #fff;
            animation: spin 1s ease-in-out infinite;
        }

        @keyframes spin {
            to { transform: rotate(360deg); }
        }

        .message {
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 20px;
            font-weight: 500;
        }

        .message.success {
            background: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }

        .message.error {
            background: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }

        /* Modal样式 */
        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            z-index: 1000;
            animation: fadeIn 0.3s;
        }

        .modal.active {
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .modal-content {
            background: white;
            border-radius: 12px;
            padding: 30px;
            max-width: 800px;
            max-height: 90vh;
            overflow-y: auto;
            width: 90%;
            animation: slideUp 0.3s;
        }

        @keyframes slideUp {
            from { transform: translateY(50px); opacity: 0; }
            to { transform: translateY(0); opacity: 1; }
        }

        .modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
        }

        .modal-header h2 {
            color: #333;
        }

        .close-btn {
            background: none;
            border: none;
            font-size: 28px;
            cursor: pointer;
            color: #999;
            line-height: 1;
        }

        .close-btn:hover {
            color: #333;
        }

        .execution-result-inline {
            margin-top: 15px;
            padding: 15px;
            background: #f9f9f9;
            border-radius: 8px;
            border-left: 4px solid #667eea;
        }

        .execution-result-inline.success {
            border-left-color: #4caf50;
        }

        .execution-result-inline.error {
            border-left-color: #f44336;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🚀 AI Worker - 智能测试平台</h1>
            <p>AI Worker可自动生成测试用例，根据用例解析MR；还可以快捷录入API自动化测试用例，帮助你更高效地进行测试工作。</p>
        </div>

        <div class="content">
            <!-- 主Tab导航 -->
            <div class="main-tabs">
                <button class="main-tab active" onclick="switchMainTab('ai-test')">🤖 AI测试</button>
                <button class="main-tab" onclick="switchMainTab('case-input')">📝 CASE录入</button>
                </div>

            <!-- AI测试 Tab内容 -->
            <div id="ai-test-tab" class="main-tab-content active">
                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
                    <h2>AI测试项目</h2>
                    <button class="btn btn-primary" onclick="window.location.href='/project/create'">➕ 新建项目</button>
            </div>

                <div id="projects-container" class="projects-grid">
                    <div class="empty-state">
                        <div class="loading"></div>
                        <h3>加载中...</h3>
                </div>
                </div>
            </div>

            <!-- 用例录入 Tab内容 -->
            <div id="case-input-tab" class="main-tab-content">
                <div class="case-input-container">
                    <!-- 子Tab导航 -->
                    <div class="sub-tabs">
                        <button class="sub-tab active" onclick="switchSubTab('upload')">📤 上传用例</button>
                        <button class="sub-tab" onclick="switchSubTab('list')">📋 用例列表</button>
                        <button class="sub-tab" onclick="switchSubTab('debug')">🐛 调试执行</button>
                        <button class="sub-tab" onclick="switchSubTab('params')">⚙️ 参数管理</button>
                </div>

                    <!-- 上传用例 -->
                    <div id="upload-tab" class="sub-tab-content active">
                        <h2 style="margin-bottom: 20px;">上传新的测试用例</h2>
                        <div id="upload-message"></div>
                        <form id="upload-form">
                <div class="form-group">
                                <label for="title">用例标题 *</label>
                                <input type="text" id="title" name="title" placeholder="例如: 用户登录接口" required>
                </div>
                <div class="form-group">
                                <label for="module">所属模块</label>
                                <select id="module" name="module">
                                    <option value="">请选择模块</option>
                                    <!-- 模块选项将通过JavaScript动态加载 -->
                                </select>
                </div>
                <div class="form-group">
                                <label for="curl">cURL 命令 * (从Chrome浏览器复制)</label>
                                <textarea id="curl" name="curl" placeholder="粘贴从浏览器复制的curl命令..." required></textarea>
                </div>
                            <button type="submit" class="btn btn-primary">
                                <span id="upload-btn-text">📤 上传用例</span>
                            </button>
                        </form>
                    </div>

                    <!-- 用例列表 -->
                    <div id="list-tab" class="sub-tab-content">
                        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
                            <h2>测试用例列表</h2>
                            <button class="btn btn-secondary" onclick="loadCases()">🔄 刷新</button>
                </div>
                        <div id="case-list" class="case-list">
                            <div class="empty-state">
                                <div>📦</div>
                                <p>暂无测试用例，请先上传</p>
                </div>
            </div>
                </div>
                
                    <!-- 调试执行 -->
                    <div id="debug-tab" class="sub-tab-content">
                        <h2 style="margin-bottom: 20px;">调试执行测试用例</h2>
                        <div id="debug-message"></div>
                    <div class="form-group">
                            <label for="case-id">用例ID *</label>
                            <input type="text" id="case-id" placeholder="输入要执行的用例ID">
                    </div>
                        <button class="btn btn-success" onclick="executeCase()">
                            <span id="execute-btn-text">▶️ 执行用例</span>
                        </button>
                        <div id="execution-result" style="margin-top: 20px;"></div>
                </div>

                    <!-- 参数管理 -->
                    <div id="params-tab" class="sub-tab-content">
                        <h2 style="margin-bottom: 20px;">全局参数管理</h2>
                        <p style="color: #666; margin-bottom: 20px;">
                            这里显示所有已保存的参数，可以在测试用例中使用 <code>${param_name}</code> 格式引用
                        </p>
                        <button class="btn btn-secondary" onclick="loadAllParameters()" style="margin-bottom: 20px;">🔄 刷新参数</button>
                        <div id="params-list" style="background: #f9f9f9; border-radius: 8px; padding: 15px;">
                            <div class="empty-state">
                                <div>⚙️</div>
                                <p>暂无参数</p>
                    </div>
                </div>
                </div>
                </div>
            </div>
                </div>
    </div>

    <!-- 编辑用例 Modal -->
    <div id="edit-modal" class="modal">
        <div class="modal-content">
            <div class="modal-header">
                <h2>编辑测试用例</h2>
                <button class="close-btn" onclick="closeEditModal()">&times;</button>
                </div>
            <div id="edit-message"></div>
            <form id="edit-form">
                <input type="hidden" id="edit-case-id">
                <div class="form-group">
                    <label for="edit-title">标题</label>
                    <input type="text" id="edit-title" required>
                </div>
                <div class="form-group">
                    <label for="edit-domain">域名</label>
                    <input type="text" id="edit-domain" required>
            </div>
                <div class="form-group">
                    <label for="edit-path">URL路径</label>
                    <input type="text" id="edit-path" required>
                </div>
                <div class="form-group">
                    <label for="edit-method">请求方法</label>
                    <input type="text" id="edit-method" required>
                </div>
                <div class="form-group">
                    <label for="edit-headers">Headers (JSON格式)</label>
                    <textarea id="edit-headers" required></textarea>
                </div>
                <div class="form-group">
                    <label for="edit-body">请求体 (JSON格式)</label>
                    <textarea id="edit-body" required></textarea>
                    <div style="font-size: 0.9em; color: #666; margin-top: 5px;">
                        💡 提示：选中文本后可以添加为参数
                    </div>
                </div>
                
                <!-- 参数管理区域 -->
                <div style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 15px;">
                    <h3 style="font-size: 1.1em; margin-bottom: 10px;">⚙️ 当前用例参数</h3>
                    <div id="edit-case-params" style="min-height: 40px;">
                        <p style="color: #999; font-size: 0.9em;">暂无参数</p>
                    </div>
                </div>
                
                <div style="display: flex; gap: 10px;">
                    <button type="submit" class="btn btn-primary">💾 保存</button>
                    <button type="button" class="btn btn-secondary" onclick="closeEditModal()">取消</button>
                </div>
            </form>
        </div>
    </div>
    
    <!-- 浮动添加参数按钮 -->
    <div id="floating-add-param-btn" style="
        position: fixed;
        display: none;
        z-index: 1001;
        background: linear-gradient(135deg, #0891b2 0%, #06b6d4 100%);
        color: white;
        padding: 8px 16px;
        border-radius: 6px;
        font-size: 13px;
        font-weight: 600;
        cursor: pointer;
        box-shadow: 0 4px 12px rgba(8, 145, 178, 0.3);
        transition: all 0.2s;
        white-space: nowrap;
    " onclick="showAddParamForm()">
        ➕ 添加为参数
    </div>

    <!-- 添加参数表单（内联） -->
    <div id="add-param-inline-form" style="
        position: fixed;
        display: none;
        z-index: 1002;
        background: white;
        padding: 20px;
        border-radius: 10px;
        box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
        min-width: 320px;
    ">
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
            <h3 style="margin: 0; font-size: 16px; color: #0f172a;">添加参数</h3>
            <button onclick="closeAddParamForm()" style="
                background: none;
                border: none;
                font-size: 24px;
                color: #94a3b8;
                cursor: pointer;
                padding: 0;
                width: 28px;
                height: 28px;
                border-radius: 50%;
                transition: all 0.2s;
            ">&times;</button>
        </div>
        <div id="add-param-message" style="margin-bottom: 10px;"></div>
        <div style="margin-bottom: 15px;">
            <label style="display: block; margin-bottom: 6px; font-weight: 600; font-size: 13px; color: #475569;">选中的值</label>
            <input type="text" id="param-value" readonly style="
                width: 100%;
                padding: 10px;
                border: 2px solid #e2e8f0;
                border-radius: 6px;
                background: #f8fafc;
                font-size: 13px;
                color: #64748b;
            ">
        </div>
        <div style="margin-bottom: 15px;">
            <label style="display: block; margin-bottom: 6px; font-weight: 600; font-size: 13px; color: #475569;">参数名称 *</label>
            <input type="text" id="param-name" placeholder="例如: user_id" style="
                width: 100%;
                padding: 10px;
                border: 2px solid #e2e8f0;
                border-radius: 6px;
                font-size: 14px;
                transition: all 0.2s;
            ">
            <div style="font-size: 12px; color: #94a3b8; margin-top: 5px;">
                使用时格式：<code style="background: #f1f5f9; padding: 2px 6px; border-radius: 3px;">\${param_name}</code>
            </div>
        </div>
        <div style="display: flex; gap: 10px;">
            <button onclick="submitAddParam()" style="
                flex: 1;
                padding: 10px 20px;
                background: linear-gradient(135deg, #10b981 0%, #059669 100%);
                color: white;
                border: none;
                border-radius: 6px;
                font-weight: 600;
                cursor: pointer;
                transition: all 0.2s;
                box-shadow: 0 2px 8px rgba(16, 185, 129, 0.2);
            " id="submit-param-btn">✅ 添加</button>
            <button onclick="closeAddParamForm()" style="
                padding: 10px 20px;
                background: #e2e8f0;
                color: #475569;
                border: none;
                border-radius: 6px;
                font-weight: 600;
                cursor: pointer;
                transition: all 0.2s;
            ">取消</button>
        </div>
    </div>

    <script>
        // 全局变量
        let currentEditingCase = null;
        let selectedText = '';
        let currentTextarea = null;

        // 主Tab切换
        function switchMainTab(tabName) {
            document.querySelectorAll('.main-tab').forEach(t => t.classList.remove('active'));
            document.querySelectorAll('.main-tab-content').forEach(c => c.classList.remove('active'));
            
            event.target.classList.add('active');
            document.getElementById(tabName + '-tab').classList.add('active');

            // 切换到AI测试时加载项目
            if (tabName === 'ai-test') {
                loadProjects();
            }
            // 切换到用例录入时加载用例列表
            else if (tabName === 'case-input') {
                // 默认不自动加载，等用户切换到列表tab时再加载
            }
        }

        // 子Tab切换（用例录入）
        function switchSubTab(tabName) {
            document.querySelectorAll('.sub-tab').forEach(t => t.classList.remove('active'));
            document.querySelectorAll('.sub-tab-content').forEach(c => c.classList.remove('active'));
            
            event.target.classList.add('active');
            document.getElementById(tabName + '-tab').classList.add('active');

            // 切换到用例列表时自动加载
            if (tabName === 'list') {
                loadCases();
            } else if (tabName === 'params') {
                loadAllParameters();
            }
        }

        // 页面加载时加载项目列表
        window.addEventListener('load', () => {
            loadProjects();
        });

        // 删除项目
        async function deleteProject(projectId, projectName) {
            if (!confirm(`确定要删除项目"${projectName}"吗？\n\n此操作将删除项目及其所有相关数据（测试用例、代码分析等），且无法恢复！`)) {
                return;
            }
            
            try {
                const response = await fetch(`/api/project/${projectId}`, {
                    method: 'DELETE'
                });
                
                const result = await response.json();
                
                if (result.success) {
                    alert('✅ 项目删除成功！');
                    loadProjects(); // 重新加载项目列表
                } else {
                    alert('❌ 删除失败: ' + result.error);
                }
            } catch (error) {
                alert('❌ 删除失败: ' + error.message);
            }
        }

        // 加载AI测试项目列表
        async function loadProjects() {
            const container = document.getElementById('projects-container');
            container.innerHTML = '<div class="empty-state"><div class="loading"></div><h3>加载中...</h3></div>';
            
            try {
                const response = await fetch('/api/projects');
                const result = await response.json();
                
                if (result.success && result.projects.length > 0) {
                    container.innerHTML = result.projects.map(p => {
                        const createdAt = new Date(p.created_at).toLocaleString('zh-CN', {
                            year: 'numeric',
                            month: '2-digit',
                            day: '2-digit',
                            hour: '2-digit',
                            minute: '2-digit'
                        });
                        return `
                            <div class="project-card" onclick="window.location.href='/project/${p.id}'">
                                <div class="project-info">
                                    <h3>${p.name}</h3>
                                    <p>${p.description || '暂无描述'}</p>
                                    <div class="project-meta">📅 创建时间: ${createdAt}</div>
                                </div>
                                <div class="project-actions" onclick="event.stopPropagation()">
                                    <button class="btn btn-primary" onclick="window.location.href='/project/${p.id}/testcases'">测试用例</button>
                                    <button class="btn btn-primary" onclick="window.location.href='/project/${p.id}/analysis'">代码分析</button>
                                    <button class="btn btn-delete btn-icon" onclick="deleteProject(${p.id}, '${p.name}')" title="删除项目"><span>🗑️ 删除</span></button>
                                </div>
                            </div>
                        `;
                    }).join('');
                } else {
                    container.innerHTML = '<div class="empty-state"><h3>📦</h3><p>暂无项目，点击右上角创建新项目</p></div>';
                }
            } catch (error) {
                container.innerHTML = `<div class="empty-state"><h3>❌</h3><p>加载失败: ${error.message}</p></div>`;
            }
        }

        // ==================== Case Input 功能 ====================

        // 加载模块列表
        async function loadModules() {
            try {
                const response = await fetch('/api/case-modules');
                const result = await response.json();
                
                if (result.success && result.modules) {
                    const select = document.getElementById('module');
                    select.innerHTML = '<option value="">请选择模块</option>';
                    result.modules.forEach(module => {
                        const option = document.createElement('option');
                        option.value = module;
                        option.textContent = module;
                        select.appendChild(option);
                    });
                }
            } catch (error) {
                console.error('加载模块列表失败:', error);
            }
        }

        // 页面加载时加载模块列表
        loadModules();

        // 上传用例
        document.getElementById('upload-form').addEventListener('submit', async (e) => {
            e.preventDefault();
            
            const btn = document.getElementById('upload-btn-text');
            btn.innerHTML = '<span class="loading"></span> 上传中...';
            
            const title = document.getElementById('title').value;
            const module = document.getElementById('module').value;
            const curl = document.getElementById('curl').value;
            
            try {
                const response = await fetch('/api/case-input/cases', {
                method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ title, module, curl_command: curl })
                });
                
                const result = await response.json();
                
                if (result.success) {
                    showMessage('upload-message', '✅ 用例上传成功！ID: ' + result.data.case_id, 'success');
                    document.getElementById('upload-form').reset();
                } else {
                    showMessage('upload-message', '❌ ' + result.error, 'error');
                }
            } catch (error) {
                showMessage('upload-message', '❌ 上传失败: ' + error.message, 'error');
            } finally {
                btn.innerHTML = '📤 上传用例';
            }
        });

        // 加载用例列表
        async function loadCases() {
            const container = document.getElementById('case-list');
            container.innerHTML = '<div class="empty-state"><div class="loading"></div><p>加载中...</p></div>';
            
            try {
                const response = await fetch('/api/case-input/cases');
                const result = await response.json();
                
                if (result.success && result.data.length > 0) {
                    container.innerHTML = result.data.map(c => `
                        <div class="case-item" id="case-item-${c.id}">
                            <div class="case-header">
                                <div>
                                    <div class="case-title">${c.title}</div>
                                    <div class="case-id">ID: ${c.id}</div>
                                </div>
                                <div class="case-actions">
                                    <button class="btn btn-primary" onclick="editCase(${c.id})">✏️ 编辑</button>
                                    <button class="btn btn-success" onclick="executeCaseInline(${c.id})">▶️ 执行</button>
                                    <button class="btn btn-danger" onclick="deleteCase(${c.id})">🗑️ 删除</button>
                                </div>
                            </div>
                            <div style="margin-bottom: 10px;">
                                <span style="font-weight: 600;">方法:</span>
                                <span class="method-badge method-${c.method}">${c.method}</span>
                                ${c.module ? `<span style="margin-left: 15px; font-weight: 600;">模块:</span> <span style="padding: 3px 10px; background: linear-gradient(135deg, #0891b2 0%, #06b6d4 100%); color: white; border-radius: 5px; font-size: 0.9em; box-shadow: 0 2px 6px rgba(8, 145, 178, 0.2);">${c.module}</span>` : ''}
                            </div>
                            <div style="margin-bottom: 10px; word-break: break-all;">
                                <span style="font-weight: 600;">URL:</span> ${c.domain}${c.url_path}
                            </div>
                            <div style="color: #999; font-size: 13px;">
                                创建时间: ${c.created_at}
                            </div>
                            <div id="execution-result-${c.id}"></div>
                        </div>
                    `).join('');
                } else {
                    container.innerHTML = '<div class="empty-state"><div>📦</div><p>暂无测试用例</p></div>';
                }
            } catch (error) {
                container.innerHTML = `<div class="empty-state"><div>❌</div><p>加载失败: ${error.message}</p></div>`;
            }
        }

        // 在列表中内联执行用例
        async function executeCaseInline(caseId) {
            const resultContainer = document.getElementById(`execution-result-${caseId}`);
            resultContainer.innerHTML = '<div class="execution-result-inline"><div class="loading"></div> 执行中...</div>';
            
            try {
                const response = await fetch(`/api/case-input/cases/${caseId}/execute`, {
                    method: 'POST'
                });
                
                const result = await response.json();
                
                if (result.success) {
                    const data = result.data;
                    const statusClass = data.success ? 'success' : 'error';
                    
                    let html = `<div class="execution-result-inline ${statusClass}">`;
                    html += `<div style="margin-bottom: 10px;"><strong>执行结果:</strong> ${data.success ? '✅ 成功' : '❌ 失败'}</div>`;
                    html += `<div style="margin-bottom: 10px;"><strong>状态码:</strong> ${data.status_code || 'N/A'} | <strong>耗时:</strong> ${data.execution_time?.toFixed(3)}秒</div>`;
                    
                    if (data.error_message) {
                        html += `<div style="margin-bottom: 10px; color: red;"><strong>错误:</strong> ${data.error_message}</div>`;
                    }
                    
                    if (data.response_body) {
                        const responseStr = typeof data.response_body === 'string' ? data.response_body : JSON.stringify(data.response_body, null, 2);
                        html += `<details style="margin-top: 10px;">`;
                        html += `<summary style="cursor: pointer; font-weight: bold;">📄 查看响应体</summary>`;
                        html += `<pre style="background: #f0f0f0; padding: 10px; border-radius: 4px; overflow-x: auto; margin-top: 10px; max-height: 300px;">${responseStr}</pre>`;
                        html += `</details>`;
                    }
                    
                    html += '</div>';
                    resultContainer.innerHTML = html;
                } else {
                    resultContainer.innerHTML = `<div class="execution-result-inline error">❌ ${result.error}</div>`;
                }
            } catch (error) {
                resultContainer.innerHTML = `<div class="execution-result-inline error">❌ 执行失败: ${error.message}</div>`;
            }
        }

        // 执行用例（调试Tab）
        async function executeCase() {
            const caseId = document.getElementById('case-id').value;
            if (!caseId) {
                showMessage('debug-message', '❌ 请输入用例ID', 'error');
                return;
            }

            await executeCaseById(parseInt(caseId));
        }

        async function executeCaseById(caseId) {
            const btn = document.getElementById('execute-btn-text');
            if (btn) btn.innerHTML = '<span class="loading"></span> 执行中...';
            
            const resultContainer = document.getElementById('execution-result');
            if (resultContainer) resultContainer.innerHTML = '<div class="empty-state"><div class="loading"></div><p>执行中...</p></div>';
            
            try {
                const response = await fetch(`/api/case-input/cases/${caseId}/execute`, {
                    method: 'POST'
                });
                
                const result = await response.json();
                
                if (result.success) {
                    const data = result.data;
                    let html = '<div style="background: #f9f9f9; padding: 20px; border-radius: 8px; margin-top: 20px;">';
                    html += `<div style="margin-bottom: 15px;"><strong>执行状态:</strong> ${data.success ? '✅ 成功' : '❌ 失败'}</div>`;
                    html += `<div style="margin-bottom: 15px;"><strong>状态码:</strong> ${data.status_code || 'N/A'}</div>`;
                    html += `<div style="margin-bottom: 15px;"><strong>执行时间:</strong> ${data.execution_time?.toFixed(3)}秒</div>`;
                    
                    if (data.error_message) {
                        html += `<div style="margin-bottom: 15px; color: red;"><strong>错误信息:</strong> ${data.error_message}</div>`;
                    }
                    
                    if (data.response_body) {
                        html += `<div style="margin-bottom: 10px;"><strong>响应体:</strong></div>`;
                        html += `<pre style="background: #f0f0f0; padding: 10px; border-radius: 4px; overflow-x: auto;">${JSON.stringify(data.response_body, null, 2)}</pre>`;
                    }
                    
                    html += '</div>';
                    
                    if (resultContainer) {
                        resultContainer.innerHTML = html;
            } else {
                        showMessage('debug-message', '✅ 执行成功！状态码: ' + data.status_code, 'success');
                    }
                } else {
                    if (resultContainer) {
                        resultContainer.innerHTML = `<div class="message error">❌ ${result.error}</div>`;
                    } else {
                        showMessage('debug-message', '❌ ' + result.error, 'error');
                    }
                }
            } catch (error) {
                if (resultContainer) {
                    resultContainer.innerHTML = `<div class="message error">❌ 执行失败: ${error.message}</div>`;
                } else {
                    showMessage('debug-message', '❌ 执行失败: ' + error.message, 'error');
                }
            } finally {
                if (btn) btn.innerHTML = '▶️ 执行用例';
            }
        }

        // 编辑用例
        async function editCase(caseId) {
            try {
                const response = await fetch(`/api/case-input/cases/${caseId}`);
                const result = await response.json();
                
                if (result.success) {
                    const c = result.data;
                    currentEditingCase = c;
                    
                    document.getElementById('edit-case-id').value = c.id;
                    document.getElementById('edit-title').value = c.title;
                    document.getElementById('edit-domain').value = c.domain;
                    document.getElementById('edit-path').value = c.url_path;
                    document.getElementById('edit-method').value = c.method;
                    document.getElementById('edit-headers').value = JSON.stringify(c.headers, null, 2);
                    document.getElementById('edit-body').value = JSON.stringify(c.body, null, 2);
                    
                    // 加载用例参数
                    loadCaseParameters(caseId);
                    
                    // 添加划词监听器
                    setupTextSelection();
                    
                    document.getElementById('edit-modal').classList.add('active');
                }
            } catch (error) {
                alert('加载失败: ' + error.message);
            }
        }
        
        // 加载用例参数
        async function loadCaseParameters(caseId) {
            try {
                const response = await fetch(`/api/case-input/cases/${caseId}/parameters`);
                const result = await response.json();
                
                const container = document.getElementById('edit-case-params');
                if (result.success && result.data && result.data.length > 0) {
                    container.innerHTML = result.data.map(p => `
                        <div style="display: flex; justify-content: space-between; align-items: center; padding: 8px; background: white; border-radius: 5px; margin-bottom: 5px;">
                            <span style="font-family: 'Courier New', monospace; color: #0891b2; font-weight: 600;">\${${p.param_name}}</span>
                            <span style="color: #666; font-size: 0.9em;">${p.param_value}</span>
                        </div>
                    `).join('');
                } else {
                    container.innerHTML = '<p style="color: #999; font-size: 0.9em;">暂无参数</p>';
                }
            } catch (error) {
                console.error('加载参数失败:', error);
            }
        }
        
        // 设置文本选择监听
        function setupTextSelection() {
            // textarea 元素（Headers 和 Body）
            const textareas = [document.getElementById('edit-headers'), document.getElementById('edit-body')];
            textareas.forEach(textarea => {
                textarea.removeEventListener('mouseup', handleTextSelection);
                textarea.addEventListener('mouseup', handleTextSelection);
                textarea.removeEventListener('keyup', handleTextSelection);
                textarea.addEventListener('keyup', handleTextSelection);
            });
            
            // input 元素（域名和 URL 路径）
            const inputs = [document.getElementById('edit-domain'), document.getElementById('edit-path')];
            inputs.forEach(input => {
                input.removeEventListener('mouseup', handleInputSelection);
                input.addEventListener('mouseup', handleInputSelection);
                input.removeEventListener('keyup', handleInputSelection);
                input.addEventListener('keyup', handleInputSelection);
            });
        }
        
        // 处理 textarea 文本选择
        function handleTextSelection(e) {
            const textarea = e.target;
            const start = textarea.selectionStart;
            const end = textarea.selectionEnd;
            currentTextarea = textarea;
            
            if (start !== end && start !== null && end !== null) {
                selectedText = textarea.value.substring(start, end).trim();
                
                if (selectedText && selectedText.length > 0) {
                    // 获取 textarea 元素的位置
                    const rect = textarea.getBoundingClientRect();
                    
                    // 计算选中文本在 textarea 中的大致位置
                    const textBeforeSelection = textarea.value.substring(0, start);
                    const lines = textBeforeSelection.split('\n');
                    const currentLine = lines.length - 1;
                    const charInLine = lines[lines.length - 1].length;
                    
                    // 估算行高（基于字体大小）
                    const styles = window.getComputedStyle(textarea);
                    const fontSize = parseFloat(styles.fontSize);
                    const lineHeight = parseFloat(styles.lineHeight) || fontSize * 1.5;
                    
                    // 估算字符宽度
                    const charWidth = getTextWidth('M', textarea); // 使用 M 作为平均宽度
                    
                    // 显示浮动按钮
                    const floatingBtn = document.getElementById('floating-add-param-btn');
                    floatingBtn.style.display = 'block';
                    
                    // 计算按钮位置（显示在 textarea 右下角附近，更可靠）
                    let left = rect.left + Math.min(charInLine * charWidth, rect.width - 20);
                    let top = rect.top + (currentLine + 1) * lineHeight + 5;
                    
                    // 如果计算的位置超出 textarea 范围，则显示在 textarea 底部中间
                    if (top > rect.bottom || left > rect.right) {
                        left = rect.left + rect.width / 2 - 75; // 居中显示
                        top = rect.bottom + 5;
                    }
                    
                    // 确保按钮在视口内
                    const btnWidth = 150;
                    if (left + btnWidth > window.innerWidth) {
                        left = window.innerWidth - btnWidth - 10;
                    }
                    if (left < 10) {
                        left = 10;
                    }
                    
                    // 如果按钮会超出底部，显示在 textarea 上方
                    if (top + 40 > window.innerHeight) {
                        top = rect.top - 40;
                    }
                    
                    floatingBtn.style.left = left + 'px';
                    floatingBtn.style.top = top + 'px';
                } else {
                    hideFloatingButton();
                }
            } else {
                // 隐藏浮动按钮
                hideFloatingButton();
            }
        }
        
        // 处理 input 文本选择
        function handleInputSelection(e) {
            const input = e.target;
            const start = input.selectionStart;
            const end = input.selectionEnd;
            
            if (start !== end && start !== null && end !== null) {
                selectedText = input.value.substring(start, end).trim();
                currentTextarea = input;
                
                if (selectedText && selectedText.length > 0) {
                    // 获取 input 元素的位置
                    const rect = input.getBoundingClientRect();
                    
                    // 计算光标位置（粗略估算，基于字符位置比例）
                    const textBeforeCursor = input.value.substring(0, start);
                    const textWidth = getTextWidth(textBeforeCursor, input);
                    const selectedTextWidth = getTextWidth(selectedText, input);
                    
                    // 显示浮动按钮
                    const floatingBtn = document.getElementById('floating-add-param-btn');
                    floatingBtn.style.display = 'block';
                    
                    // 计算按钮位置
                    let left = rect.left + textWidth + selectedTextWidth / 2;
                    let top = rect.bottom + 5;
                    
                    // 确保按钮在视口内
                    const btnWidth = 150;
                    if (left + btnWidth > window.innerWidth) {
                        left = window.innerWidth - btnWidth - 10;
                    }
                    if (left < 10) {
                        left = 10;
                    }
                    
                    // 如果按钮会超出底部，显示在输入框上方
                    if (top + 40 > window.innerHeight) {
                        top = rect.top - 40;
                    }
                    
                    floatingBtn.style.left = left + 'px';
                    floatingBtn.style.top = top + 'px';
                } else {
                    hideFloatingButton();
                }
            } else {
                hideFloatingButton();
            }
        }
        
        // 辅助函数：计算文本宽度
        function getTextWidth(text, inputElement) {
            const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement('canvas'));
            const context = canvas.getContext('2d');
            const styles = window.getComputedStyle(inputElement);
            context.font = `${styles.fontSize} ${styles.fontFamily}`;
            return context.measureText(text).width;
        }
        
        // 隐藏浮动按钮
        function hideFloatingButton() {
            document.getElementById('floating-add-param-btn').style.display = 'none';
        }
        
        // 显示添加参数表单
        function showAddParamForm() {
            const floatingBtn = document.getElementById('floating-add-param-btn');
            const form = document.getElementById('add-param-inline-form');
            
            // 设置表单位置（使用fixed定位，直接使用浮动按钮的位置）
            const btnLeft = parseFloat(floatingBtn.style.left);
            const btnTop = parseFloat(floatingBtn.style.top);
            
            form.style.display = 'block';
            form.style.left = btnLeft + 'px';
            form.style.top = (btnTop + 40) + 'px';
            
            // 设置值
            document.getElementById('param-value').value = selectedText;
            document.getElementById('param-name').value = '';
            document.getElementById('param-name').focus();
            
            // 隐藏浮动按钮
            hideFloatingButton();
        }
        
        // 关闭添加参数表单
        function closeAddParamForm() {
            document.getElementById('add-param-inline-form').style.display = 'none';
            document.getElementById('add-param-message').innerHTML = '';
            selectedText = '';
        }
        
        // 提交添加参数
        async function submitAddParam() {
            const paramName = document.getElementById('param-name').value.trim();
            const paramValue = document.getElementById('param-value').value;
            const caseId = document.getElementById('edit-case-id').value;
            
            if (!paramName) {
                showMessage('add-param-message', '参数名称不能为空', 'error');
                return;
            }
            
            const submitBtn = document.getElementById('submit-param-btn');
            submitBtn.disabled = true;
            submitBtn.textContent = '添加中...';
            
            try {
                const response = await fetch(`/api/case-input/cases/${caseId}/parameters`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        param_name: paramName,
                        param_value: paramValue,
                        json_path: ''
                    })
                });
                
                const result = await response.json();
                
                if (result.success) {
                    // 替换文本中的值为参数引用
                    if (currentTextarea) {
                        const currentValue = currentTextarea.value;
                        const newValue = currentValue.replace(paramValue, `\${${paramName}}`);
                        currentTextarea.value = newValue;
                    }
                    
                    // 重新加载参数列表
                    loadCaseParameters(caseId);
                    
                    showMessage('add-param-message', '✅ 参数添加成功！', 'success');
                    
                    setTimeout(() => {
                        closeAddParamForm();
                    }, 800);
                } else {
                    showMessage('add-param-message', '❌ ' + result.error, 'error');
                }
            } catch (error) {
                showMessage('add-param-message', '❌ 添加失败: ' + error.message, 'error');
            } finally {
                submitBtn.disabled = false;
                submitBtn.textContent = '✅ 添加';
            }
        }
        
        // 点击页面其他地方关闭浮动按钮和表单
        document.addEventListener('click', function(e) {
            const floatingBtn = document.getElementById('floating-add-param-btn');
            const form = document.getElementById('add-param-inline-form');
            
            if (!floatingBtn.contains(e.target) && !form.contains(e.target)) {
                // 检查是否点击在 textarea 或 input 框内
                if (!e.target.closest('textarea, input[type="text"]')) {
                    hideFloatingButton();
                    if (form.style.display === 'block') {
                        closeAddParamForm();
                    }
                }
            }
        });

        // 关闭编辑Modal
        function closeEditModal() {
            document.getElementById('edit-modal').classList.remove('active');
            document.getElementById('edit-message').innerHTML = '';
            currentEditingCase = null;
        }

        // 保存编辑
        document.getElementById('edit-form').addEventListener('submit', async (e) => {
            e.preventDefault();
            
            const caseId = document.getElementById('edit-case-id').value;
            
            try {
                const data = {
                    title: document.getElementById('edit-title').value,
                    domain: document.getElementById('edit-domain').value,
                    url_path: document.getElementById('edit-path').value,
                    method: document.getElementById('edit-method').value,
                    headers: JSON.parse(document.getElementById('edit-headers').value),
                    body: JSON.parse(document.getElementById('edit-body').value)
                };
                
                const response = await fetch(`/api/case-input/cases/${caseId}`, {
                    method: 'PUT',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(data)
                });
                
                const result = await response.json();
                
                if (result.success) {
                    showMessage('edit-message', '✅ 保存成功！', 'success');
                    setTimeout(() => {
                        closeEditModal();
                        loadCases();
                    }, 1000);
                } else {
                    showMessage('edit-message', '❌ ' + result.error, 'error');
                }
            } catch (error) {
                showMessage('edit-message', '❌ 保存失败: ' + error.message, 'error');
            }
        });

        // 删除用例
        async function deleteCase(caseId) {
            if (!confirm('确定要删除这个测试用例吗？')) return;
            
            try {
                const response = await fetch(`/api/case-input/cases/${caseId}`, {
                    method: 'DELETE'
                });
                
                const result = await response.json();
                
                if (result.success) {
                    loadCases();
                } else {
                    alert('删除失败: ' + result.error);
                }
            } catch (error) {
                alert('删除失败: ' + error.message);
            }
        }

        // 加载所有参数
        async function loadAllParameters() {
            const container = document.getElementById('params-list');
            container.innerHTML = '<div class="empty-state"><div class="loading"></div><p>加载中...</p></div>';
            
            try {
                const response = await fetch('/api/case-input/parameters');
                const result = await response.json();
                
                if (result.success && Object.keys(result.data).length > 0) {
                    container.innerHTML = Object.entries(result.data).map(([name, value]) => `
                        <div style="display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #e0e0e0;">
                            <span style="font-weight: bold; color: #0891b2;">\${${name}}</span>
                            <span style="color: #666; font-family: 'Courier New', monospace;">${value}</span>
                        </div>
                    `).join('');
                } else {
                    container.innerHTML = '<div class="empty-state"><div>⚙️</div><p>暂无参数</p></div>';
                }
            } catch (error) {
                container.innerHTML = `<div class="empty-state"><div>❌</div><p>加载失败: ${error.message}</p></div>`;
            }
        }

        // 显示消息
        function showMessage(containerId, message, type) {
            const container = document.getElementById(containerId);
            container.innerHTML = `<div class="message ${type}">${message}</div>`;
            setTimeout(() => {
                container.innerHTML = '';
            }, 5000);
        }
    </script>
</body>
</html>
